package com.stox.ui.javafx.charting.widget.axis;

import javafx.scene.text.TextAlignment;

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.stox.util.Constant;

@Component("valueAxis")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ValueAxis extends AbstractVerticalAxis {
	
	/** We use these for auto ranging to pick a user friendly tick unit. We handle tick units in the range of 1e-10 to 1e+12 */
    private static final double[] TICK_UNIT_DEFAULTS = {
        1.0E-10d, 2.5E-10d, 5.0E-10d, 1.0E-9d, 2.5E-9d, 5.0E-9d, 1.0E-8d, 2.5E-8d, 5.0E-8d, 1.0E-7d, 2.5E-7d, 5.0E-7d,
        1.0E-6d, 2.5E-6d, 5.0E-6d, 1.0E-5d, 2.5E-5d, 5.0E-5d, 1.0E-4d, 2.5E-4d, 5.0E-4d, 0.0010d, 0.0025d, 0.0050d,
        0.01d, 0.025d, 0.05d, 0.1d, 0.25d, 0.5d, 1.0d, 2.5d, 5.0d, 10.0d, 25.0d, 50.0d, 100.0d, 250.0d, 500.0d,
        1000.0d, 2500.0d, 5000.0d, 10000.0d, 25000.0d, 50000.0d, 100000.0d, 250000.0d, 500000.0d, 1000000.0d,
        2500000.0d, 5000000.0d, 1.0E7d, 2.5E7d, 5.0E7d, 1.0E8d, 2.5E8d, 5.0E8d, 1.0E9d, 2.5E9d, 5.0E9d, 1.0E10d,
        2.5E10d, 5.0E10d, 1.0E11d, 2.5E11d, 5.0E11d, 1.0E12d, 2.5E12d, 5.0E12d
    };
    
    private boolean updateGrid = false;
    
	public String stringValueOf(double value) {
		String text = "";
		if(value>= 1000000000) {
			text = "B";
			value /= 1000000000;
		}else if(value >= 1000000) {
			text = "M";
			value /= 1000000;
		}else if(value >= 1000) {
			text = "K";
			value /= 1000;
		}
		return String.valueOf(Constant.numberFormat.format(value)+text);
	}

	public void paint() {
		super.paint();
		double textHeight = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().getFontMetrics(gc.getFont()).getLineHeight();
		
		double height = getChart().getCenter().getLayoutBounds().getHeight();
		
		double highest = getTargetPlot().getHighest();
		double lowest = getTargetPlot().getLowest();
		int numOfTickMarks = (int)Math.floor(height/(textHeight+AbstractVerticalAxis.padding*2));
		double tickRange = Math.abs(highest - lowest)/numOfTickMarks; 
				
		for(double def : TICK_UNIT_DEFAULTS) {
			if(tickRange <= def) {
				tickRange = def;
				break;
			}
		}
		
		double highestTickValue = Math.ceil(highest/tickRange)*tickRange;
		double lowestTickValue = Math.floor(lowest/tickRange)*tickRange;
		
		if(lowestTickValue < highestTickValue && tickRange > 0) {
			if(updateGrid)
				getChart().getGrid().getYs().clear();
			while(lowestTickValue < highestTickValue) {
				double y = height - (lowestTickValue - lowest)*(height/(highest - lowest));
				double x = TextAlignment.LEFT.equals(gc.getTextAlign()) ? 0 : getWidth();
				gc.strokeText(stringValueOf(lowestTickValue), x, y);
				double tickLength = 5*(TextAlignment.LEFT.equals(gc.getTextAlign()) ? -1 : 1);
				gc.strokeLine(getWidth() - x + tickLength, y, getWidth() - x - tickLength, y);
				if(updateGrid)
					getChart().getGrid().getYs().add(y);
				lowestTickValue += tickRange;
			}
		}
	}

	public boolean isUpdateGrid() {
		return updateGrid;
	}

	public void setUpdateGrid(boolean updateGrid) {
		this.updateGrid = updateGrid;
	}
}
